from django.conf.urls.defaults import patterns
from django.contrib.admin.options import IncorrectLookupParameters
#import re
from django.http import HttpResponseRedirect
from django.contrib import admin
from utils import get_prev_item, get_next_item, get_max
from django.utils.http import http_date
import time

class OrderingAdmin(admin.ModelAdmin):
    ordering = ('order',)
    list_display = ('adm_move_up', 'adm_move_down')
    save_on_top = True
#    def __call__(self, request, url):
#        if url:
#            match = re.match('^move_(?P<direction>up|down)/(?P<pk>[^/]+)', url)
#            if match:
#                return self.move(request, match.group('direction'), match.group('pk'))
#        return super(OrderingAdmin, self).__call__(request, url)

    def get_urls(self):
        urls = super(OrderingAdmin, self).get_urls()
        my_urls = patterns('', (
            '^move_(?P<direction>up|down)/(?P<pk>[^/]+)',
            self.admin_site.admin_view(self.move),
        ))
        return my_urls + urls

    def save_model(self, request, obj, form, change):
        try:
            objects = self.get_objects(request)
        except IncorrectLookupParameters:
            # TODO make good
            objects = self.model.objects.all()
        if obj.order == 0:
            obj.order = get_max(objects, 'order') + 1
        obj.save()

#    def changelist_view(self, request, extra_context=None):
#        if extra_context is None: extra_context = {}
#        return super(OrderingAdmin, self).changelist_view(request, extra_context)

    def get_objects(self, request=None):
        from django.contrib.admin.views.main import ChangeList
        try: # django 1.1
            cl = ChangeList(request, self.model, self.list_display, self.list_display_links, self.list_filter,
                self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self)
        except (TypeError, AttributeError):  # django 1.0
            cl = ChangeList(request, self.model, self.list_display, self.list_display_links, self.list_filter,
                self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self)
        return cl.query_set

    def redirect_after_move(self, request):
        response = HttpResponseRedirect('../../?%s' % request.GET.urlencode())
        response['Cache-Control'] = 'no-cache'
        response['Expires'] = http_date(time.time() - 1)
        return response

    def move(self, request, direction, pk):
        current = self.get_objects(request).get(id=pk)
        objects = current.objects_filter()

        if objects.values('order').distinct().count() != objects.count():
            self._reorder(objects)

        try:
            if direction == 'up':
                prev = get_prev_item(objects, 'order', current.order)
                current.order, prev.order = prev.order, current.order
                prev.save()
            elif direction == 'down':
                next = get_next_item(objects, 'order', current.order)
                current.order, next.order = next.order, current.order
                next.save()
            else:
                raise ValueError, 'Incorrect direction `%s`' % direction
        except AttributeError:
            pass

        current.save()
        return self.redirect_after_move(request)

    def _reorder(self, objects):
        for i, item in enumerate(objects):
            order = i + 1
            if item.order != order:
                item.order = order
                item.save()
